package com.sugar.real.estate.module.business.service.apartment;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sugar.real.estate.framework.common.pojo.PageParam;
import com.sugar.real.estate.framework.common.pojo.PageResult;
import com.sugar.real.estate.framework.common.util.object.BeanUtils;
import com.sugar.real.estate.module.business.controller.admin.apartment.vo.ApartmentPageReqVO;
import com.sugar.real.estate.module.business.controller.admin.apartment.vo.ApartmentRespVO;
import com.sugar.real.estate.module.business.controller.admin.apartment.vo.ApartmentSaveReqVO;
import com.sugar.real.estate.module.business.controller.admin.apartment.vo.ApartmentUpdateReqVO;
import com.sugar.real.estate.module.business.controller.app.apartment.vo.*;
import com.sugar.real.estate.module.business.controller.app.info.vo.AppInfoRespVO;
import com.sugar.real.estate.module.business.dal.dataobject.apartment.ApartmentDO;
import com.sugar.real.estate.module.business.dal.dataobject.apartment.ApartmentHouseTypeDO;
import com.sugar.real.estate.module.business.dal.dataobject.apartment.ApartmentSalespersonDO;
import com.sugar.real.estate.module.business.dal.dataobject.dicttype.BizDictDataDO;
import com.sugar.real.estate.module.business.dal.dataobject.infohouse.InfoHouseDO;
import com.sugar.real.estate.module.business.dal.dataobject.openedcity.OpenedCityDO;
import com.sugar.real.estate.module.business.dal.dataobject.userbuildingconsult.UserBuildingConsultDO;
import com.sugar.real.estate.module.business.dal.dataobject.userfollow.UserFollowDO;
import com.sugar.real.estate.module.business.dal.mysql.apartment.ApartmentHouseTypeMapper;
import com.sugar.real.estate.module.business.dal.mysql.apartment.ApartmentMapper;
import com.sugar.real.estate.module.business.dal.mysql.apartment.ApartmentSalespersonMapper;
import com.sugar.real.estate.module.business.dal.mysql.dicttype.BizDictDataMapper;
import com.sugar.real.estate.module.business.dal.mysql.infohouse.InfoHouseMapper;
import com.sugar.real.estate.module.business.dal.mysql.openedcity.OpenedCityMapper;
import com.sugar.real.estate.module.business.dal.mysql.userbuildingconsult.UserBuildingConsultMapper;
import com.sugar.real.estate.module.business.dal.mysql.userfollow.UserFollowMapper;
import com.sugar.real.estate.module.business.service.dicttype.BizDictTypeService;
import com.sugar.real.estate.module.business.service.openedcity.OpenedCityService;
import com.sugar.real.estate.module.business.util.I18nUtil;
import com.sugar.real.estate.module.infra.controller.admin.file.vo.file.FileUploadReqVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.sugar.real.estate.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.real.estate.module.business.enums.ErrorCodeConstants.*;

/**
 * 楼盘/公寓 Service 实现类
 *
 * @author Ysugar
 */
@Slf4j
@Service
@Validated
public class ApartmentServiceImpl implements ApartmentService {

    @Resource
    private ApartmentMapper apartmentMapper;
    @Resource
    private ApartmentHouseTypeMapper apartmentHouseTypeMapper;
    @Resource
    private ApartmentSalespersonMapper apartmentSalespersonMapper;
    @Resource
    private OpenedCityService openedCityService;
    @Resource
    private InfoHouseMapper infoHouseMapper;
    @Resource
    private UserFollowMapper userFollowMapper;
    @Resource
    private UserBuildingConsultMapper userBuildingConsultMapper;
    @Resource
    private BizDictTypeService dictTypeService;
    @Resource
    private BizDictDataMapper bizDictDataMapper;
    @Resource
    private OpenedCityMapper openedCityMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createApartment(ApartmentSaveReqVO createReqVO) {
        Long[] locationIds = createReqVO.getLocationIds();
        if (Objects.nonNull(locationIds) && locationIds.length == 2) {
            createReqVO.setCityId(locationIds[0]);
            createReqVO.setCountyId(locationIds[1]);
        }else {
            throw exception(OPENED_CITY_NO_SELECT);
        }
        /*if (Objects.nonNull(locationIds) && locationIds.length > 0) {
            int length = locationIds.length;
            switch (length) {
                case 3:
                    createReqVO.setCountyId(locationIds[2]);
                case 2:
                    createReqVO.setCityId(locationIds[1]);
                case 1:
                    createReqVO.setProvinceId(locationIds[0]);
            }
        } else {
            // 尝试获取获取省市区ID
            String[] location = createReqVO.getLocation();
            if (Objects.nonNull(location)) {
                int length = location.length;
                if (length > 0) {
                    Long provinceId = openedCityService.getSameOpenedCity(location[0], 0L);
                    Long cityId = length >= 2 ? openedCityService.getSameOpenedCity(location[1], provinceId) : null;
                    Long countyId = length >= 3 ? openedCityService.getSameOpenedCity(location[2], cityId) : null;

                    createReqVO.setProvinceId(provinceId).setCityId(cityId).setCountyId(countyId);
                }
            }
        }*/

        // 插入
        ApartmentDO apartment = BeanUtils.toBean(createReqVO, ApartmentDO.class);
        apartmentMapper.insert(apartment);

        Long houseId = apartment.getId();

        // 插入资讯关联信息
        Long[] infoIds = createReqVO.getInfoIds();
        if (null != infoIds){
            for (Long infoId : infoIds) {
                if (null != infoId){
                    InfoHouseDO infoHouseDO = new InfoHouseDO().setType(false).setInfoId(infoId).setHouseId(houseId);
                    infoHouseMapper.insert(infoHouseDO);
                }
            }
        }

        // 返回
        return apartment.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateApartment(ApartmentSaveReqVO updateReqVO) {
        // 校验存在
        Long houseId = updateReqVO.getId();
        validateApartmentExists(houseId);

        Long[] locationIds = updateReqVO.getLocationIds();
        if (Objects.nonNull(locationIds) && locationIds.length == 2) {
            updateReqVO.setCityId(locationIds[0]);
            updateReqVO.setCountyId(locationIds[1]);
        }else {
            throw exception(OPENED_CITY_NO_SELECT);
        }

        // 尝试获取获取省市区ID
        /*String[] location = updateReqVO.getLocation();
        if (Objects.nonNull(location)) {
            int length = location.length;
            if (length > 0) {
                Long provinceId = openedCityService.getSameOpenedCity(location[0], 0L);
                Long cityId = length >= 2 ? openedCityService.getSameOpenedCity(location[1], provinceId) : null;
                Long countyId = length >= 3 ? openedCityService.getSameOpenedCity(location[2], cityId) : null;

                updateReqVO.setProvinceId(provinceId).setCityId(cityId).setCountyId(countyId);
            }
        } else {
            Long[] locationIds = updateReqVO.getLocationIds();
            if (Objects.nonNull(locationIds) && locationIds.length > 0) {
                int length = locationIds.length;
                switch (length) {
                    case 3:
                        updateReqVO.setCountyId(locationIds[2]);
                    case 2:
                        updateReqVO.setCityId(locationIds[1]);
                    case 1:
                        updateReqVO.setProvinceId(locationIds[0]);
                }
            }
        }*/

        // 删除原来的资讯关联信息
        infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery().eq(InfoHouseDO::getType, 0).eq(InfoHouseDO::getHouseId, houseId));

        // 插入新的
        Long[] newInfoIds = updateReqVO.getInfoIds();
        if (null != newInfoIds){
            for (Long infoId : newInfoIds) {
                if (null != infoId){
                    InfoHouseDO infoHouseDO = new InfoHouseDO().setType(false).setInfoId(infoId).setHouseId(houseId);
                    infoHouseMapper.insert(infoHouseDO);
                }
            }
        }

        // 更新
        ApartmentDO updateObj = BeanUtils.toBean(updateReqVO, ApartmentDO.class);
        apartmentMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteApartment(Long id) {
        // 校验存在
        validateApartmentExists(id);
        // 删除
        apartmentMapper.deleteById(id);

        // 删除子表
        deleteApartmentHouseTypeByApartmentId(id);
        deleteApartmentSalespersonByApartmentId(id);

        // 删除资讯关联信息
        infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery()
                .eq(InfoHouseDO::getType, 0).eq(InfoHouseDO::getHouseId, id));
        // 删除用户关注
        userFollowMapper.delete(Wrappers.<UserFollowDO>lambdaQuery()
                .eq(UserFollowDO::getType, 0).eq(UserFollowDO::getFollowId, id));
        // 删除用户咨询
        userBuildingConsultMapper.delete(Wrappers.<UserBuildingConsultDO>lambdaQuery()
                .eq(UserBuildingConsultDO::getType, 0).eq(UserBuildingConsultDO::getFollowId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteApartmentListByIds(List<Long> ids) {
        // 校验存在
        validateApartmentExists(ids);
        // 删除
        apartmentMapper.deleteByIds(ids);

        // 删除子表
        deleteApartmentHouseTypeByApartmentIds(ids);
        deleteApartmentSalespersonByApartmentIds(ids);

        for (Long id : ids) {
            // 删除资讯关联信息
            infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery()
                    .eq(InfoHouseDO::getType, 0).eq(InfoHouseDO::getHouseId, id));
            // 删除用户关注
            userFollowMapper.delete(Wrappers.<UserFollowDO>lambdaQuery()
                    .eq(UserFollowDO::getType, 0).eq(UserFollowDO::getFollowId, id));
            // 删除用户咨询
            userBuildingConsultMapper.delete(Wrappers.<UserBuildingConsultDO>lambdaQuery()
                    .eq(UserBuildingConsultDO::getType, 0).eq(UserBuildingConsultDO::getFollowId, id));
        }
    }

    private void validateApartmentExists(List<Long> ids) {
        List<ApartmentDO> list = apartmentMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(APARTMENT_NOT_EXISTS);
        }
    }

    private void validateApartmentExists(Long id) {
        if (apartmentMapper.selectById(id) == null) {
            throw exception(APARTMENT_NOT_EXISTS);
        }
    }

    @Override
    public ApartmentRespVO getApartment(Long id) {
        ApartmentDO apartmentDO = apartmentMapper.selectById(id);
        if (Objects.nonNull(apartmentDO)) {
            ApartmentRespVO respVO = BeanUtils.toBean(apartmentDO, ApartmentRespVO.class);
            List<Long> locationIds = new ArrayList<>();
            /*if (Objects.nonNull(apartmentDO.getProvinceId()))
                locationIds.add(apartmentDO.getProvinceId());*/
            if (Objects.nonNull(apartmentDO.getCityId()))
                locationIds.add(apartmentDO.getCityId());
            if (Objects.nonNull(apartmentDO.getCountyId()))
                locationIds.add(apartmentDO.getCountyId());

            List<InfoHouseDO> infoHouses = infoHouseMapper.selectList(Wrappers.<InfoHouseDO>lambdaQuery()
                    .eq(InfoHouseDO::getHouseId, apartmentDO.getId())
                    .eq(InfoHouseDO::getType, 0));
            respVO.setLocationIds(locationIds)
                    .setInfoIds(infoHouses.stream().map(InfoHouseDO::getInfoId).collect(Collectors.toList()));
            return respVO;
        }
        return null;
    }

    @Override
    public PageResult<ApartmentRespVO> getApartmentPage(ApartmentPageReqVO pageReqVO) {
        PageResult<ApartmentRespVO> pageResult = BeanUtils.toBean(apartmentMapper.selectPage(pageReqVO), ApartmentRespVO.class);
        pageResult.getList().forEach(apartment -> {
            // 查询关注数
            apartment.setFollowCount(userFollowMapper.selectCount(UserFollowDO::getFollowId, apartment.getId(), UserFollowDO::getType, 0));
            // 查询咨询数
            apartment.setConsultCount(userBuildingConsultMapper.selectCount(UserBuildingConsultDO::getFollowId, apartment.getId(), UserBuildingConsultDO::getType, 0));
        });
        return pageResult;
    }

    @Override
    public PageResult<AppApartmentSimpleRespVO> appGetApartmentPage(AppApartmentPageReqVO reqVO) {
        String projectProgress = reqVO.getProjectProgress();
        if (Objects.nonNull(projectProgress)) {
            reqVO.setProjectProgress(dictTypeService.appGetAllDictDataLabel(5L, projectProgress));
        }

        Long countyId = reqVO.getCountyId();
        // 若名称不为空，则筛选地址有没有这个名称的
        if (StrUtil.isNotBlank(reqVO.getName())){
            if (countyId == null){
                String name = StrUtil.upperFirst(reqVO.getName());
                OpenedCityDO openedCityDO = openedCityMapper.selectOne(Wrappers.<OpenedCityDO>lambdaQuery().ne(OpenedCityDO::getParentId, 0)
                        .nested(o -> o.eq(OpenedCityDO::getNameEnUs, name).or().eq(OpenedCityDO::getNameZhCn, name))
                        .last("LIMIT 1"));
                if (openedCityDO != null){
                    reqVO.setCountyId(openedCityDO.getId());
                    reqVO.setName(null);
                }
            }
        }

        PageResult<AppApartmentSimpleRespVO> pageResult = apartmentMapper.appGetApartmentPage(reqVO);
        boolean chinese = I18nUtil.isChinese();
        return BeanUtils.toBean(pageResult, AppApartmentSimpleRespVO.class,
                o -> o.setShowImage(o.getShowImages().get(0))
                        .setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setProjectLight(chinese ? o.getProjectLightZhCn() : o.getProjectLightEnUs())
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));
    }

    @Override
    public List<AppApartmentSimpleRespVO> getApartmentListByMap(AppApartmentPageReqVO reqVO) {
        boolean chinese = I18nUtil.isChinese();

        Long countyId = reqVO.getCountyId();
        // 若名称不为空，则筛选地址有没有这个名称的
        if (StrUtil.isNotBlank(reqVO.getName())){
            if (countyId == null){
                String name = StrUtil.upperFirst(reqVO.getName());
                OpenedCityDO openedCityDO = openedCityMapper.selectOne(Wrappers.<OpenedCityDO>lambdaQuery().ne(OpenedCityDO::getParentId, 0)
                        .nested(o -> o.eq(OpenedCityDO::getNameEnUs, name).or().eq(OpenedCityDO::getNameZhCn, name))
                        .last("LIMIT 1"));
                if (openedCityDO != null){
                    reqVO.setCountyId(openedCityDO.getId());
                    reqVO.setName(null);
                }
            }
        }

        return BeanUtils.toBean(apartmentMapper.appGetApartmentPage(reqVO).getList(), AppApartmentSimpleRespVO.class,
                o -> o.setShowImage(o.getShowImages().get(0))
                        .setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setProjectLight(chinese ? o.getProjectLightZhCn() : o.getProjectLightEnUs())
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));
    }

    @Override
    public AppApartmentDetailRespVO appGetApartment(Long id, Long userId) {
        ApartmentDO apartmentDO = apartmentMapper.selectById(id);
        boolean chinese = I18nUtil.isChinese();
        AppApartmentDetailRespVO respVO = BeanUtils.toBean(apartmentDO, AppApartmentDetailRespVO.class,
                o -> o.setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setProjectLight(chinese ? o.getProjectLightZhCn() : o.getProjectLightEnUs())
                        .setMainHouseType(chinese ? o.getMainHouseTypeZhCn() : o.getMainHouseTypeEnUs())
                        .setProjectProgress(I18nUtil.getMessage(o, "getProjectProgress"))
                        .setBuilder(I18nUtil.getMessage(o, "getBuilder"))
                        .setDesigner(I18nUtil.getMessage(o, "getDesigner"))
                        .setContent(I18nUtil.getMessage(o, "getContent"))
                        .setProjectLight(chinese ? o.getProjectLightZhCn() : o.getProjectLightEnUs())
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));

        // 获取资讯数量
        Long count = infoHouseMapper.selectCount(Wrappers.<InfoHouseDO>lambdaQuery()
                .eq(InfoHouseDO::getHouseId, id)
                .eq(InfoHouseDO::getType, 0));

        respVO.setHaveMoreInfo(count > 1);
        // 获取资讯
        if (count > 0){
            AppInfoRespVO appInfoRespVO = infoHouseMapper.selectListCustom(id, 0);
            appInfoRespVO.setTitle(I18nUtil.getMessage(appInfoRespVO, "getTitle"))
                    .setContent(I18nUtil.getMessage(appInfoRespVO, "getContent"))
                    .setAuthor(I18nUtil.getMessage(appInfoRespVO, "getAuthor"));
            respVO.setInfo(appInfoRespVO);
        }

        // 获取户型信息
        List<ApartmentHouseTypeDO> houseTypeList = apartmentHouseTypeMapper.selectList(Wrappers.<ApartmentHouseTypeDO>lambdaQuery()
                .eq(ApartmentHouseTypeDO::getApartmentId, respVO.getId()));
        respVO.setHouseTypeList(BeanUtils.toBean(houseTypeList, AppApartmentHouseTypeDetailRespVO.class,
                o -> o/*.setStatus(I18nUtil.getMessage(o, "getStatus"))*/
                        .setHouseTypeName(dictTypeService.appGetAllDictDataLabel(1L, o.getHouseType()))));
        // 获取销售信息
        List<ApartmentSalespersonDO> salespersonList = apartmentSalespersonMapper.selectList(Wrappers.<ApartmentSalespersonDO>lambdaQuery()
                .eq(ApartmentSalespersonDO::getApartmentId, respVO.getId()));
        respVO.setSalespersonList(BeanUtils.toBean(salespersonList, AppApartmentSalespersonDetailRespVO.class,
                o -> o.setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())));

        // 获取当前用户是否关注
        if (Objects.nonNull(userId)){
            Long isUserFollow = userFollowMapper.selectCount(Wrappers.<UserFollowDO>lambdaQuery()
                    .eq(UserFollowDO::getUserId, userId)
                    .eq(UserFollowDO::getType, 0)
                    .eq(UserFollowDO::getFollowId, id));
            respVO.setUserFollow(isUserFollow > 0);
        }

        // 更新查看数量
        apartmentMapper.update(ApartmentDO::getId, apartmentDO.getId(), ApartmentDO::getLookCount, apartmentDO.getLookCount() + 1);

        return respVO;
    }

    @Override
    public void importApartmentExcel(FileUploadReqVO uploadReqVO) throws IOException {
        final int[] i = {2};

        try {
            EasyExcel.read(uploadReqVO.getFile().getInputStream(), new ReadListener<Map<Integer, String>>() {
                @Override
                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                    try {
                        ApartmentDO apartment = new ApartmentDO();
                        apartment.setNameZhCn(data.get(0));
                        apartment.setNameEnUs(data.get(1));
                        apartment.setShowImages(Arrays.stream(data.get(2).split(",")).collect(Collectors.toList()));
                        String data3 = data.get(3);
                        if (StrUtil.isNotBlank(data3))
                            apartment.setShowVideos(Arrays.stream(data3.split(",")).collect(Collectors.toList()));
                        apartment.setMainHouseTypeZhCn(data.get(4));
                        apartment.setMainHouseTypeEnUs(data.get(4));
                        String data5 = data.get(5);
                        if (StrUtil.isNotBlank(data5))
                            apartment.setPriceMin(new BigDecimal(data5));
                        String data6 = data.get(6);
                        if (StrUtil.isNotBlank(data6))
                            apartment.setPriceMax(new BigDecimal(data6));
                        String data7 = data.get(7);
                        if (StrUtil.isNotBlank(data7))
                            apartment.setTagsZhCn(Arrays.stream(data7.split(",")).collect(Collectors.toList()));
                        String data8 = data.get(8);
                        if (StrUtil.isNotBlank(data8))
                            apartment.setTagsEnUs(Arrays.stream(data8.split(",")).collect(Collectors.toList()));
                        String data9 = data.get(9);
                        if (StrUtil.isNotBlank(data9))
                            apartment.setProjectLightZhCn(Arrays.stream(data9.split(",")).collect(Collectors.toList()));
                        String data10 = data.get(10);
                        if (StrUtil.isNotBlank(data10))
                            apartment.setProjectLightEnUs(Arrays.stream(data10.split(",")).collect(Collectors.toList()));
                        apartment.setProjectType(data.get(11));
                        apartment.setProjectProgressZhCn(data.get(12));
                        apartment.setProjectProgressEnUs(data.get(13));
                        String data14 = data.get(14);
                        if (StrUtil.isNotBlank(data14))
                            apartment.setCompletionTime(LocalDateTimeUtil.parseDate(data14 + "-01"));
                        apartment.setBuilderZhCn(data.get(15));
                        apartment.setBuilderEnUs(data.get(16));
                        apartment.setDesignerZhCn(data.get(17));
                        apartment.setDesignerEnUs(data.get(18));
                        apartment.setContentZhCn(data.get(19));
                        apartment.setContentEnUs(data.get(20));
                        apartment.setPoint(data.get(21));
                        apartment.setPointDetail(data.get(22));
                        apartment.setTotalAmount(data.get(23));

                        // 插入
                        apartmentMapper.insert(apartment);
                        i[0] = i[0] + 1;
                    }catch (Throwable e){
                        log.error("导入楼盘数据失败：", e);
                        throw exception(SERVER_BUSY);
                    }
                }

                // 读取完毕
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                }
            }).sheet().doRead();
        }catch (Throwable e){
            throw exception(IMPORT_EXCEL_ERROR, i[0]);
        }
    }

    @Override
    public void importExcel(FileUploadReqVO uploadReqVO, Long apartmentId) {
        final int[] i = {2};

        try {
            EasyExcel.read(uploadReqVO.getFile().getInputStream(), new ReadListener<Map<Integer, String>>() {
                @Override
                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                    try {
                        ApartmentHouseTypeDO houseType = new ApartmentHouseTypeDO();
                        houseType.setApartmentId(apartmentId);
                        houseType.setShowImage(data.get(0));
                        // 查找户型
                        String houseTypeName = data.get(1);
                        BizDictDataDO bizDictDataDO = bizDictDataMapper.selectOne(Wrappers.<BizDictDataDO>lambdaQuery().eq(BizDictDataDO::getDictTypeId, 1)
                                .like(BizDictDataDO::getLabelEnUs, houseTypeName).or().like(BizDictDataDO::getLabelZhCn, houseTypeName)
                                .last("LIMIT 1"));
                        if (bizDictDataDO == null)
                            throw exception(APARTMENT_HOUSE_TYPE_NOT_EXISTS_IMPORT, i[0]);
                        houseType.setHouseType(bizDictDataDO.getValue());
                        houseType.setPriceMin(new BigDecimal(data.get(2)));
                        /*houseType.setHouseArea(new BigDecimal(data.get(3)));
                        houseType.setStatusZhCn(data.get(4));
                        houseType.setStatusEnUs(data.get(5));*/
                        houseType.setParkingSpace(data.get(3));
                        houseType.setIndoorArea(data.get(4));
                        houseType.setBalconyArea(data.get(5));

                        // 插入
                        apartmentHouseTypeMapper.insert(houseType);
                        i[0] = i[0] + 1;
                    }catch (Throwable e){
                        log.error("导入楼盘数据失败：", e);
                        throw exception(SERVER_BUSY);
                    }
                }

                // 读取完毕
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                }
            }).sheet().doRead();
        }catch (Throwable e){
            throw exception(IMPORT_EXCEL_ERROR, i[0]);
        }
    }

    // ==================== 子表（楼盘/公寓户型） ====================

    @Override
    public PageResult<ApartmentHouseTypeDO> getApartmentHouseTypePage(PageParam pageReqVO, Long apartmentId) {
        return apartmentHouseTypeMapper.selectPage(pageReqVO, apartmentId);
    }

    @Override
    public Long createApartmentHouseType(ApartmentHouseTypeDO apartmentHouseType) {
        apartmentHouseTypeMapper.insert(apartmentHouseType);
        return apartmentHouseType.getId();
    }

    @Override
    public void updateApartmentHouseType(ApartmentHouseTypeDO apartmentHouseType) {
        // 校验存在
        validateApartmentHouseTypeExists(apartmentHouseType.getId());
        // 更新
        apartmentHouseType.clean(); // 解决更新情况下：updateTime 不更新
        apartmentHouseTypeMapper.updateById(apartmentHouseType);
    }

    @Override
    public void deleteApartmentHouseType(Long id) {
        // 删除
        apartmentHouseTypeMapper.deleteById(id);
    }

    @Override
    public void deleteApartmentHouseTypeListByIds(List<Long> ids) {
        // 删除
        apartmentHouseTypeMapper.deleteByIds(ids);
    }

    @Override
    public ApartmentHouseTypeDO getApartmentHouseType(Long id) {
        return apartmentHouseTypeMapper.selectById(id);
    }

    private void validateApartmentHouseTypeExists(Long id) {
        if (apartmentHouseTypeMapper.selectById(id) == null) {
            throw exception(APARTMENT_HOUSE_TYPE_NOT_EXISTS);
        }
    }

    private void deleteApartmentHouseTypeByApartmentId(Long apartmentId) {
        apartmentHouseTypeMapper.deleteByApartmentId(apartmentId);
    }

    private void deleteApartmentHouseTypeByApartmentIds(List<Long> apartmentIds) {
        apartmentHouseTypeMapper.deleteByApartmentIds(apartmentIds);
    }

    // ==================== 子表（楼盘/公寓销售人员） ====================

    @Override
    public PageResult<ApartmentSalespersonDO> getApartmentSalespersonPage(PageParam pageReqVO, Long apartmentId) {
        return apartmentSalespersonMapper.selectPage(pageReqVO, apartmentId);
    }

    @Override
    public Long createApartmentSalesperson(ApartmentSalespersonDO apartmentSalesperson) {
        apartmentSalespersonMapper.insert(apartmentSalesperson);
        return apartmentSalesperson.getId();
    }

    @Override
    public void updateApartmentSalesperson(ApartmentSalespersonDO apartmentSalesperson) {
        // 校验存在
        validateApartmentSalespersonExists(apartmentSalesperson.getId());
        // 更新
        apartmentSalesperson.clean(); // 解决更新情况下：updateTime 不更新
        apartmentSalespersonMapper.updateById(apartmentSalesperson);
    }

    @Override
    public void deleteApartmentSalesperson(Long id) {
        // 删除
        apartmentSalespersonMapper.deleteById(id);
    }

    @Override
    public void deleteApartmentSalespersonListByIds(List<Long> ids) {
        // 删除
        apartmentSalespersonMapper.deleteByIds(ids);
    }

    @Override
    public ApartmentSalespersonDO getApartmentSalesperson(Long id) {
        return apartmentSalespersonMapper.selectById(id);
    }

    @Override
    public void updateApartmentStatus(ApartmentUpdateReqVO updateReqVO) {
        apartmentMapper.update(ApartmentDO::getId, updateReqVO.getId(), ApartmentDO::getIsShow, updateReqVO.getIsShow());
    }

    private void validateApartmentSalespersonExists(Long id) {
        if (apartmentSalespersonMapper.selectById(id) == null) {
            throw exception(APARTMENT_SALESPERSON_NOT_EXISTS);
        }
    }

    private void deleteApartmentSalespersonByApartmentId(Long apartmentId) {
        apartmentSalespersonMapper.deleteByApartmentId(apartmentId);
    }

    private void deleteApartmentSalespersonByApartmentIds(List<Long> apartmentIds) {
        apartmentSalespersonMapper.deleteByApartmentIds(apartmentIds);
    }

}